{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Simple usage of a set of MPI engines" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example assumes you've started a cluster of N engines (4 in this example) as part\n", "of an MPI world. \n", "\n", "Our documentation describes [how to create an MPI profile](https://ipyparallel.readthedocs.io/en/stable/tutorial/process.html#using-ipython-parallel-with-mpi)\n", "and explains [basic MPI usage of the IPython cluster](https://ipyparallel.readthedocs.io/en/stable/reference/mpi.html).\n", "\n", "\n", "For the simplest possible way to start 4 engines that belong to the same MPI world, \n", "you can run this in a terminal:\n", "\n", "
\n",
    "ipcluster start --engines=MPI -n 4\n",
    "
\n", "\n", "or start an MPI cluster from the cluster tab if you have one configured.\n", "\n", "Once the cluster is running, we can connect to it and open a view into it:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true, "jupyter": { "outputs_hidden": true } }, "outputs": [], "source": [ "import ipyparallel as ipp\n", "rc = ipp.Client()\n", "view = rc[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's define a simple function that gets the MPI rank from each engine." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true, "jupyter": { "outputs_hidden": true } }, "outputs": [], "source": [ "@view.remote(block=True)\n", "def mpi_rank():\n", " from mpi4py import MPI\n", " comm = MPI.COMM_WORLD\n", " return comm.Get_rank()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 3, 2]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mpi_rank()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get a mapping of IPython IDs and MPI rank (these do not always match),\n", "you can use the get_dict method on AsyncResults." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{0: 0, 1: 1, 2: 3, 3: 2}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mpi_rank.block = False\n", "ar = mpi_rank()\n", "ar.get_dict()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With %%px cell magic, the next cell will actually execute *entirely on each engine*:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\u001b[0;31mOut[0:8]: \u001b[0m{'data': 1, 'rank': 0}" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\u001b[0;31mOut[1:8]: \u001b[0m{'data': 4, 'rank': 1}" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\u001b[0;31mOut[2:8]: \u001b[0m{'data': 16, 'rank': 3}" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\u001b[0;31mOut[3:8]: \u001b[0m{'data': 9, 'rank': 2}" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%px\n", "from mpi4py import MPI\n", "\n", "comm = MPI.COMM_WORLD\n", "size = comm.Get_size()\n", "rank = comm.Get_rank()\n", "\n", "if rank == 0:\n", " data = [(i+1)**2 for i in range(size)]\n", "else:\n", " data = None\n", "data = comm.scatter(data, root=0)\n", "\n", "assert data == (rank+1)**2, 'data=%s, rank=%s' % (data, rank)\n", "{\n", " 'data': data,\n", " 'rank': rank,\n", "}" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.6" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }